home *** CD-ROM | disk | FTP | other *** search
- This file is ulimit.def, from which is created ulimit.c.
- It implements the builtin "ulimit" in Bash.
-
- Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 1, or (at your option) any later
- version.
-
- Bash is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License along
- with Bash; see the file COPYING. If not, write to the Free Software
- Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $PRODUCES ulimit.c
-
- $BUILTIN ulimit
- $FUNCTION ulimit_builtin
- $SHORT_DOC ulimit [-SHacdmstfpn [limit]]
- Ulimit provides control over the resources available to processes
- started by the shell, on systems that allow such control. If an
- option is given, it is interpreted as follows:
-
- -S use the `soft' resource limit
- -H use the `hard' resource limit
- -a all current limits are reported
- -c the maximum size of core files created
- -d the maximum size of a process's data segment
- -m the maximum resident set size
- -s the maximum stack size
- -t the maximum amount of cpu time in seconds
- -f the maximum size of files created by the shell
- -p the pipe buffer size
- -n the maximum number of open file descriptors
-
- If LIMIT is given, it is the new value of the specified resource.
- Otherwise, the current value of the specified resource is printed.
- If no option is given, then -f is assumed. Values are in 1k
- increments, except for -t, which is in seconds, and -p, which is in
- increments of 512 bytes.
- $END
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/param.h>
- #include <errno.h>
- #include "../shell.h"
- #include "pipesize.h"
-
- #if !defined (errno)
- extern int errno;
- #endif
-
- #if defined (HAVE_RESOURCE)
- #include <sys/time.h>
- #include <sys/resource.h>
- #else
- #include <sys/times.h>
- #endif
-
- #if defined (_POSIX_VERSION)
- #include <limits.h>
- #endif
-
- /* Check for the most basic symbols. If they aren't present, this
- system's <sys/resource.h> isn't very useful to us. */
- #if !defined (RLIMIT_FSIZE)
- # undef HAVE_RESOURCE
- #endif
-
- /* **************************************************************** */
- /* */
- /* Ulimit builtin and Hacks. */
- /* */
- /* **************************************************************** */
-
- /* Block size for ulimit operations. */
- #define ULIMIT_BLOCK_SIZE ((long)1024)
-
- #define u_FILE_SIZE 0x001
- #define u_MAX_BREAK_VAL 0x002
- #define u_PIPE_SIZE 0x004
- #define u_CORE_FILE_SIZE 0x008
- #define u_DATA_SEG_SIZE 0x010
- #define u_PHYS_MEM_SIZE 0x020
- #define u_CPU_TIME_LIMIT 0x040
- #define u_STACK_SIZE 0x080
- #define u_NUM_OPEN_FILES 0x100
-
- #define u_ALL_LIMITS 0x7ff
-
- #ifndef RLIM_INFINITY
- # define RLIM_INFINITY 0x7fffffff
- #endif
-
- #define LIMIT_HARD 0x01
- #define LIMIT_SOFT 0x02
-
- static long shell_ulimit ();
- static long pipesize ();
- static int open_files ();
-
- static void print_specific_limits ();
- static void print_all_limits ();
-
- static char t[2];
-
- /* Report or set limits associated with certain per-process resources.
- See the help documentation in builtins.c for a full description.
-
- Rewritten by Chet Ramey 6/30/91. */
-
- int
- ulimit_builtin (list)
- register WORD_LIST *list;
- {
- register char *s;
- int c, setting, cmd, mode, verbose_print, opt_eof;
- int all_limits, specific_limits;
- long current_limit, real_limit, limit = -1L;
- long block_factor;
-
- c = mode = verbose_print = opt_eof = 0;
-
- do
- {
- cmd = setting = all_limits = specific_limits = 0;
- block_factor = ULIMIT_BLOCK_SIZE;
-
- /* read_options: */
- if (list && !opt_eof && *list->word->word == '-')
- {
- s = &(list->word->word[1]);
- list = list->next;
-
- while (*s && (c = *s++))
- {
- switch (c)
- {
- #define ADD_CMD(x) { if (cmd) specific_limits++; cmd |= (x); }
-
- case '-': /* ulimit -- */
- opt_eof++;
- break;
-
- case 'a':
- all_limits++;
- break;
-
- case 'f':
- ADD_CMD (u_FILE_SIZE);
- break;
-
- #if defined (HAVE_RESOURCE)
- /* -S and -H are modifiers, not real options. */
- case 'S':
- mode |= LIMIT_SOFT;
- break;
-
- case 'H':
- mode |= LIMIT_HARD;
- break;
-
- case 'c':
- ADD_CMD (u_CORE_FILE_SIZE);
- break;
-
- case 'd':
- ADD_CMD (u_DATA_SEG_SIZE);
- break;
-
- #if !defined (USGr4)
- case 'm':
- ADD_CMD (u_PHYS_MEM_SIZE);
- break;
- #endif /* USGr4 */
-
- case 't':
- ADD_CMD (u_CPU_TIME_LIMIT);
- block_factor = 1; /* seconds */
- break;
-
- case 's':
- ADD_CMD (u_STACK_SIZE);
- break;
- #endif /* HAVE_RESOURCE */
-
- case 'p':
- ADD_CMD (u_PIPE_SIZE);
- block_factor = 512;
- break;
-
- case 'n':
- ADD_CMD (u_NUM_OPEN_FILES);
- block_factor = 1;
- break;
-
- default: /* error_case: */
- t[0] = c;
- t[1] = '\0';
- bad_option (t);
- #if !defined (HAVE_RESOURCE)
- builtin_error("usage: ulimit [-afnp] [new limit]");
- #else
- builtin_error("usage: ulimit [-SHacmdstfnp] [new limit]");
- #endif
- return (EXECUTION_FAILURE);
- }
- }
- }
-
- if (all_limits)
- {
- print_all_limits (mode);
- return (EXECUTION_SUCCESS);
- }
-
- if (specific_limits)
- {
- print_specific_limits (cmd, mode);
- if (list)
- verbose_print++;
- continue;
- }
-
- if (cmd == 0)
- cmd = u_FILE_SIZE;
-
- /* If an argument was supplied for the command, then we want to
- set the limit. Note that `ulimit something' means a command
- of -f with argument `something'. */
- if (list)
- {
- if (opt_eof || (*list->word->word != '-'))
- {
- s = list->word->word;
- list = list->next;
- if (sscanf (s, "%ld", &limit) != 1)
- {
- if (strcmp (s, "unlimited") == 0)
- limit = RLIM_INFINITY;
- else
- {
- builtin_error ("bad non-numeric arg `%s'", s);
- return (EXECUTION_FAILURE);
- }
- }
- setting++;
- }
- else if (!opt_eof)
- verbose_print++;
- }
-
- if (limit == RLIM_INFINITY)
- block_factor = 1;
-
- real_limit = limit * block_factor;
-
- /* If more than one option is given, list each in a verbose format,
- the same that is used for -a. */
- if (!setting && verbose_print)
- {
- print_specific_limits (cmd, mode);
- continue;
- }
-
- current_limit = shell_ulimit (cmd, real_limit, 0, mode);
-
- if (setting)
- {
- #if !defined (HAVE_RESOURCE)
- /* USG systems do not allow limits to be raised by any user
- other than root. */
- if ((current_limit < real_limit) && (getuid () != 0))
- {
- builtin_error ("cannot raise limit: %s", strerror (EPERM));
- return (EXECUTION_FAILURE);
- }
- #endif /* !HAVE_RESOURCE */
-
- if (shell_ulimit (cmd, real_limit, 1, mode) == -1)
- {
- builtin_error ("cannot raise limit: %s", strerror(errno));
- return (EXECUTION_FAILURE);
- }
-
- continue;
- }
- else
- {
- if (current_limit != RLIM_INFINITY)
- printf ("%ld\n", (current_limit / block_factor));
- else
- printf ("unlimited\n");
- }
- }
- while (list);
-
- return (EXECUTION_SUCCESS);
- }
-
- /* The ulimit that we call from within Bash.
-
- WHICH says which limit to twiddle; SETTING is non-zero if NEWLIM
- contains the desired new limit. Otherwise, the existing limit is
- returned. If mode & LIMIT_HARD, the hard limit is used; if
- mode & LIMIT_SOFT, the soft limit. Both may be set by specifying
- -H and -S; if both are specified, or if neither is specified, the
- soft limit will be returned.
-
- Systems without BSD resource limits can specify only u_FILE_SIZE.
- This includes most USG systems.
-
- Chet Ramey supplied the BSD resource limit code. */
-
- static long
- shell_ulimit (which, newlim, setting, mode)
- int which, setting, mode;
- long newlim;
- {
- #if defined (HAVE_RESOURCE)
- struct rlimit limit;
- int cmd;
-
- if (mode == 0)
- mode |= LIMIT_SOFT;
- #endif
-
- switch (which)
- {
- #if !defined (HAVE_RESOURCE)
-
- case u_FILE_SIZE:
- if (!setting)
- {
- /* ulimit () returns a number that is in 512 byte blocks, thus we
- must multiply it by 512 to get back to bytes. This is false
- only under HP/UX 6.x. */
- long result;
-
- result = ulimit (1, 0L);
-
- # if defined (hpux) && !defined (_POSIX_VERSION)
- return (result);
- # else
- return (result * 512);
- # endif /* hpux 6.x */
- }
- else
- return (ulimit (2, newlim / 512L));
-
- break;
-
- #else /* defined (HAVE_RESOURCE) */
-
- case u_FILE_SIZE:
- cmd = RLIMIT_FSIZE;
- goto do_ulimit;
-
- case u_CORE_FILE_SIZE:
- cmd = RLIMIT_CORE;
- goto do_ulimit;
-
- case u_DATA_SEG_SIZE:
- cmd = RLIMIT_DATA;
- goto do_ulimit;
-
- #if !defined (USGr4)
- case u_PHYS_MEM_SIZE:
- cmd = RLIMIT_RSS;
- goto do_ulimit;
- #endif /* USGr4 */
-
- case u_CPU_TIME_LIMIT:
- cmd = RLIMIT_CPU;
- goto do_ulimit;
-
- case u_STACK_SIZE:
- cmd = RLIMIT_STACK;
-
- do_ulimit:
-
- if (getrlimit (cmd, &limit) != 0)
- return ((long) -1);
-
- if (!setting)
- {
- if (mode & LIMIT_SOFT)
- return (limit.rlim_cur);
- else
- return (limit.rlim_max);
- }
- else
- {
- if (mode & LIMIT_SOFT)
- limit.rlim_cur = newlim;
- if (mode & LIMIT_HARD)
- limit.rlim_max = newlim;
-
- return (setrlimit (cmd, &limit));
- }
-
- break;
-
- #endif /* HAVE_RESOURCE */
-
- /* You can't get or set the pipe size with getrlimit, so we have to
- cheat. */
- case u_PIPE_SIZE:
- if (setting)
- {
- errno = EINVAL;
- return ((long) -1);
- }
- return (pipesize ());
-
- case u_NUM_OPEN_FILES:
- if (setting)
- {
- #if defined (HAVE_RESOURCE) && defined (RLIMIT_NOFILE)
- cmd = RLIMIT_NOFILE;
- goto do_ulimit;
- #else
- # if defined (HAVE_SETDTABLESIZE)
- return (setdtablesize (newlim));
- # else
- errno = EINVAL;
- return ((long) -1);
- # endif /* HAVE_SETDTABLESIZE */
- #endif /* !HAVE_RESOURCE || !RLIMIT_NOFILE */
- }
- else
- return ((long) open_files (mode));
-
- default:
- errno = EINVAL;
- return ((long) -1);
- }
- }
-
- static int
- open_files (mode)
- int mode;
- {
- #if !defined (RLIMIT_NOFILE)
- return (getdtablesize ());
- #else
- struct rlimit rl;
-
- getrlimit (RLIMIT_NOFILE, &rl);
- if (mode & LIMIT_SOFT)
- return (rl.rlim_cur);
- else
- return (rl.rlim_max);
- #endif
- }
-
- static long
- pipesize ()
- {
- #if defined (PIPE_BUF)
- /* This is defined on Posix systems. */
- return ((long) PIPE_BUF);
- #else
- # if defined (PIPESIZE)
- /* This is defined by running a program from the Makefile. */
- return ((long) PIPESIZE);
- # else
- errno = EINVAL;
- return ((long) -1);
- # endif /* PIPESIZE */
- #endif /* PIPE_BUF */
- }
-
- /* ulimit(2) returns information about file size limits in terms of 512-byte
- blocks. This is the factor by which to divide to turn it into information
- in terms of 1024-byte blocks. Except for hpux 6.x, which returns it in
- terms of bytes. */
- #if !defined (hpux) || defined (_POSIX_VERSION)
- # define ULIMIT_DIVISOR 2
- #else
- # define ULIMIT_DIVISOR 1024
- #endif
-
- #if defined (HAVE_RESOURCE)
-
- #if !defined (RLIM_NLIMITS)
- # define RLIM_NLIMITS 6 /* Number of resource limits. */
- #endif
-
- typedef struct {
- int option_cmd; /* The ulimit command for this limit. */
- int parameter; /* Parameter to pass to getrlimit (). */
- int block_factor; /* Blocking factor for specific limit. */
- char *description; /* Descriptive string to output. */
- } BSD_RESOURCE_LIMITS;
-
- static BSD_RESOURCE_LIMITS limits[RLIM_NLIMITS + 1] = {
- { u_CORE_FILE_SIZE, RLIMIT_CORE, 1024, "core file size (blocks)" },
- { u_DATA_SEG_SIZE, RLIMIT_DATA, 1024, "data seg size (kbytes)" },
- { u_FILE_SIZE, RLIMIT_FSIZE, 1024, "file size (blocks)" },
- #if !defined (USGr4)
- { u_PHYS_MEM_SIZE, RLIMIT_RSS, 1024, "max memory size (kbytes)" },
- #endif /* USGr4 */
- { u_STACK_SIZE, RLIMIT_STACK, 1024, "stack size (kbytes)" },
- { u_CPU_TIME_LIMIT, RLIMIT_CPU, 1, "cpu time (seconds)" },
- { 0, 0, 0, (char *)NULL }
- };
-
- static void
- print_bsd_limit (i, mode)
- int i, mode;
- {
- struct rlimit rl;
- long limit;
-
- getrlimit (limits[i].parameter, &rl);
- if (mode & LIMIT_HARD)
- limit = rl.rlim_max;
- else
- limit = rl.rlim_cur;
- printf ("%-25s", limits[i].description);
- if (limit == RLIM_INFINITY)
- printf ("unlimited\n");
- else
- printf ("%ld\n", limit / limits[i].block_factor);
- }
-
- static void
- print_specific_bsd_limits (cmd, mode)
- int cmd, mode;
- {
- register int i;
-
- for (i = 0; limits[i].option_cmd; i++)
- if (cmd & limits[i].option_cmd)
- print_bsd_limit (i, mode);
- }
- #endif /* HAVE_RESOURCE */
-
- /* Print the limits corresponding to a specific set of resources. This is
- called when an option string contains more than one character (e.g. -at),
- because limits may not be specified with that kind of argument. */
- static void
- print_specific_limits (cmd, mode)
- int cmd, mode;
- {
- if (mode == 0)
- mode |= LIMIT_SOFT;
-
- #if defined (HAVE_RESOURCE)
- print_specific_bsd_limits (cmd, mode);
- #else
- if (cmd & u_FILE_SIZE)
- printf ("%-25s%ld\n", "file size (blocks)", ulimit (1, 0L) / ULIMIT_DIVISOR);
- #endif
-
- if (cmd & u_PIPE_SIZE)
- printf ("%-25s%ld\n", "pipe size (512 bytes)", (pipesize () / 512));
-
- if (cmd & u_NUM_OPEN_FILES)
- printf ("%-25s%ld\n", "open files", open_files (mode));
- }
-
- static void
- print_all_limits (mode)
- int mode;
- {
- if (mode == 0)
- mode |= LIMIT_SOFT;
-
- print_specific_limits (u_ALL_LIMITS, mode);
- }
-